﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using mitasoft.Books.Core;
using mitasoft.Books.DataLayer;
using System.IO;
using System.Diagnostics;
using mitasoft.Books.Client.Desktop.Core;
using ICSharpCode.SharpZipLib.Zip;

namespace mitasoft.Books.Client.Desktop.Services
{
    internal class BooksDiscoveryService
    {
        private List<FileDescriptor> result;
        private Services.ApplicationMessagesService messageService;

        /// <summary>
        /// ctor
        /// </summary>
        public BooksDiscoveryService()
        {

        }

        /// <summary>
        /// Search 
        /// </summary>
        /// <param name="path">path to search</param>
        /// <returns></returns>
        public List<FileDescriptor> SearchFolder(string path)
        {
            messageService = ServiceManager.GetService<Services.ApplicationMessagesService>();
            result = new List<FileDescriptor>();

            if (Directory.Exists(path))
            {
                ProcessDirectory(path);
            }

            return result;
        }

        // Process all files in the directory passed in, recurse on any directories 
        // that are found, and process the files they contain.
        private void ProcessDirectory(string targetDirectory)
        {
            try
            {
                // Process the list of files found in the directory.
                string[] fileEntries = Directory.GetFiles(targetDirectory, "*.pdf");
                fileEntries = fileEntries.Union(Directory.GetFiles(targetDirectory, "*.chm")).ToArray();
                fileEntries = fileEntries.Union(Directory.GetFiles(targetDirectory, "*.zip").Where(CheckForBooksInZip)).ToArray();

                foreach (string fileName in fileEntries)
                    ProcessFile(fileName);

                // Recurse into subdirectories of this directory.
                string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
                foreach (string subdirectory in subdirectoryEntries)
                    ProcessDirectory(subdirectory);
            }
            catch
            {
                messageService.AddMessage("I can't read " + targetDirectory, ApplicationMessageEnum.error);
                //Debug.WriteLine("I can't read " + targetDirectory);
            }
        }

        // Insert logic for processing found files here.
        private void ProcessFile(string path)
        {
            result.Add(new FileDescriptor(path));
        }

        /// <summary>
        /// Check if zip archive contains any books
        /// </summary>
        private Func<string, bool> CheckForBooksInZip = delegate(string s)
        {
            using (ZipInputStream zipStream = new ZipInputStream(File.OpenRead(s)))
            {
                ZipEntry zipEntry;
                while ((zipEntry = zipStream.GetNextEntry()) != null)
                {
                    //return even it is encrypted
                    if (zipEntry.IsCrypted)
                    {
                        return true;
                    }
                    else if (zipEntry.IsFile)
                    {
                        if (zipEntry.Name.EndsWith("pdf") || zipEntry.Name.EndsWith("chm"))
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        };
    }
}
